package com.xxlie.auth.common;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.xxlie.auth.domain.Attach;
import com.xxlie.auth.thirdpart.alitools.AliyunOssTool;
import com.xxlie.auth.thirdpart.alitools.AliyunSmsTool;
import com.xxlie.core.common.CacheKeyUtil;
import com.xxlie.core.common.PropertiesTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

/**
 * 工具类
 */
@Component
public class CommUtil {
    @Autowired
    AliyunOssTool aliyunOssTool;

    @Autowired
    AliyunSmsTool aliyunSmsTool;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    public static String ossAttachServerDomain = PropertiesTools.getPropertyValue("aliyun_oss.endpoint");

    /**
     * 获取文件图片url地址
     *
     * @param attach
     * @return
     */
    public static Attach getFileUrl(Attach attach) {
        if (attach != null && attach.getPath() != null) {
            String newPath = getFileUrl(attach.getPath());
            attach.setPath(newPath);
        }
        return attach;
    }

    /**
     * 获取文件图片url地址
     *
     * @param path
     * @return
     */
    public static String getFileUrl(String path) {
        if (path == null)
            return null;

        //由于存在循环调用，这里判断存在前缀则不处理
        int isFull = path.indexOf("http");
        if (isFull >= 0) {
            return path;
        }

        //由于使用的地方比较多，图片上传base64的时候也不需要替换
        int isInBase64 = path.indexOf("data:image");
        if (isInBase64 >= 0) {
            return path;
        }

        return ossAttachServerDomain + "/" + path;
    }


    /**
     * 获取头像地址
     *
     * @param avatar
     * @return
     */
    public static String getUserAvatar(String avatar) {
        if (avatar == null) {
            avatar = "app/avatar.png";
        }

        return getFileUrl(avatar);
    }

    /**
     * 格式化输出几月几日
     *
     * @param date
     * @return
     */
    public static String dateFormat(Date date, String format) {
        DateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }

    /**
     * 格式化今日和之前的时间展示
     *
     * @param date
     * @return
     */
    public static String dateFormatTodayAndBefore(Date date) {
        Date currentDate = new Date();
        String today = dateFormat(currentDate, "yyyy-MM-dd");
        String formatDate = dateFormat(date, "yyyy-MM-dd");
        if (today.equals(formatDate)) {
            return dateFormat(date, "HH:mm");
        } else {
            return dateFormat(date, "MM-dd");
        }
    }

    /**
     * 获取当天0点时间
     *
     * @return
     */
    public static Date getTodayZeroTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zero = calendar.getTime();
        return zero;
    }

    /**
     * 获取明天的0时间
     *
     * @return
     */
    public static Date getTomorrowdayStartTime() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, +1);
        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        Date time = cal.getTime();
        return time;
    }

    /**
     * 发送登录短信
     *
     * @param phone
     * @param param
     * @param outId
     * @return
     */
    public Map sendLoginSms(String phone, Map param, String outId) {
        return this.sendSms(phone, param, outId, AliyunSmsTool.TEMPLATE_LOGIN);
    }

    /**
     * 发送登录短信
     *
     * @param phone
     * @param param
     * @param outId
     * @return
     */
    public Map sendRegisterSms(String phone, Map param, String outId) {
        return this.sendSms(phone, param, outId, AliyunSmsTool.TEMPLATE_RESGISTER);
    }

    /**
     * 发送指定模板短信
     *
     * @param phone
     * @param param
     * @param outId
     * @param templateCode
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Map sendSms(String phone, Map param, String outId, String templateCode) {
        Map map = new HashMap();
        try {
            SendSmsResponse sendSmsResponse = aliyunSmsTool.sendSms(phone, param, outId, templateCode);
            map.put("code", sendSmsResponse.getCode());
            map.put("message", sendSmsResponse.getMessage());
        } catch (ClientException e) {
            map.put("code", e.getErrCode());
            map.put("message", e.getErrMsg());
        }

        return map;
    }

    /**
     * 获取短信验证码
     * 固定为6位
     *
     * @return
     */
    public String getSmsCode() {
        Random random = new Random();
        char[] chars = new char[6];
        for (int i = 0; i < chars.length; i++) {
            chars[i] = (char) ('0' + random.nextInt(10));
        }
        return String.valueOf(chars);
    }

    /**
     * 随机6个字符
     *
     * @param num
     * @return
     */
    public static String randomInt(int num) {
        if (num == 0) {
            num = 6;
        }
        Random random = new Random();
        char[] chars = new char[num];
        for (int i = 0; i < chars.length; i++) {
            chars[i] = (char) ('0' + random.nextInt(10));
        }
        return String.valueOf(chars);
    }

    /**
     * 验证手机短信验证码
     *
     * @param phone
     * @param smsCode
     * @return
     */
    public boolean validateSmsCode(String phone, String smsCode) {
        if (smsCode == null || phone == null) {
            return false;
        }

        String smsCodeCache = stringRedisTemplate.opsForValue().get(CacheKeyUtil.PHONE_SMS + phone);
        if (!smsCode.equals(smsCodeCache)) {
            return false;
        }
        return true;
    }

    /**
     * 获取随机字符串
     *
     * @param length
     * @return
     */
    public static String randomString(int length) {
        char[] randomString = new char[length];
        for (int j = 0; j < randomString.length; j++) {
            randomString[j] = getChar();
        }
        return String.valueOf(randomString);
    }

    /**
     * 获取随机字符
     *
     * @return
     */
    private static char getChar() {
        Random random = new Random();
        switch (random.nextInt(3)) {
            case 0:
                return (char) ('a' + random.nextInt(26));
            case 1:
                return (char) ('A' + random.nextInt(26));
            default:
                return (char) ('0' + random.nextInt(10));
        }
    }

    /**
     * 获取音频文件OSS完整地址
     *
     * @param path
     * @return
     */
    public String getAudioUrl(String path) {
        int isFull = path.indexOf(ossAttachServerDomain);
        if (isFull >= 0) {
            return path;
        }
        return aliyunOssTool.getVideoUrl(path);
    }

    /**
     * 上传远程图片到服务器
     *
     * @param url
     * @return
     */
    public Map uploadImageFromUrl(String url) {
        Map map = new HashMap();
        map.put("path", "");
        map.put("pathFull", "");

        if (url != null && !url.equals("")) {
            //将二进制存储到文件中
            String fileName = UUID.randomUUID().toString() + "." + "jpg";
            try {
                // 构造URL
                URL urlData = new URL(url);
                // 打开连接
                URLConnection con = urlData.openConnection();
                //设置请求超时为5s
                con.setConnectTimeout(5 * 1000);
                // 输入流
                InputStream inputStream = con.getInputStream();
                // 上传头像到阿里云OSS
                String storeFileName = "app/" + fileName;
                boolean uploadSuccess = this.aliyunOssTool.uploadFileByInputStream(inputStream, storeFileName);

                if (uploadSuccess) {
                    map.put("path", storeFileName);
                    map.put("pathFull", CommUtil.getFileUrl(storeFileName));
                }
            } catch (IOException e) {
            } finally {
            }
        }

        return map;
    }

    /**
     * 获取一个月的开始时间
     *
     * @param date
     * @return
     */
    private static Date getMonthStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int index = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.add(Calendar.DATE, (1 - index));
        return calendar.getTime();
    }

    /**
     * 获取一个月的结束时间
     *
     * @param date
     * @return
     */
    private static Date getMonthEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        int index = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.add(Calendar.DATE, (-index));
        return calendar.getTime();
    }

    /**
     * 获取当前天的下一天
     *
     * @param date
     * @return
     */
    private static Date getNext(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, 1);
        return calendar.getTime();
    }

    /**
     * 获取完整的一个月时间，签到用到
     *
     * @return
     */
    public static List<String> getAllDaysMonth() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("d");
        List<String> list = new ArrayList();
        Date d = new Date();
        // 月初
        // System.out.println("月初" + sdf.format(getMonthStart(d)));
        // 月末
        //System.out.println("月末" + sdf.format(getMonthEnd(d)));

        Date date = getMonthStart(d);
        Date monthEnd = getMonthEnd(d);
        while (!date.after(monthEnd)) {
            //System.out.println(sdf.format(date));
            list.add(dateFormat.format(date));
            date = getNext(date);
        }
        return list;
    }

    /**
     * 获取指定范围随机数
     *
     * @param min
     * @param max
     * @return
     */
    public static int getRandNum(int min, int max) {
        min = (min != 0) ? min : 400;
        max = (max != 0) ? max : 2000;

        if (max <= min) {
            min = 400;
            max = 2000;
        }

        Random random = new Random();
        int result = random.nextInt(max) % (max - min + 1) + min;
        return result;
    }

    /**
     * 获取固定范围内随机数
     *
     * @return
     */
    public static int getRandNum() {
        int min = 400;
        int max = 2000;
        Random random = new Random();
        int result = random.nextInt(max) % (max - min + 1) + min;
        return result;
    }
}
